/**
 * 封装 axios 请求模块
 */
import axios from 'axios'
import { Toast } from 'vant'
import { refreshToken } from '../api/user.js'
import store from '../store/index.js'

const request = axios.create({
  baseURL: 'http://ttapi.research.itcast.cn/' // 基础路径
})

// 加载中toast实例对象
let loadingInstance = null

request.interceptors.request.use((config) => {
  loadingInstance = Toast.loading({
    message: '加载中...',
    forbidClick: true, // 禁用背景点击
    duration: 0 // 持续时间：默认2000毫秒，0表示一直显示
  })

  // 如果 不 不需要token，意思就是需要Token
  if (!config.notToken) {
    const user = store.state.user
    const token = user ? user.token : ''
    if (token) {
      config.headers.Authorization = 'Bearer ' + token
    }
  }

  return config
})

request.interceptors.response.use(
  // 响应成功（HTTP）时的拦截器
  (res) => {
    // 清除加载中弹层
    loadingInstance.clear()
    return res
  },
  // 响应失败（HTTP）时的拦截器
  (err) => {
    // response 响应信息, config 请求时的配置信息
    const { response: res, config: cfg } = err
    console.log('失败的请求发送时的配置: ', cfg)

    if (res.status === 401) {
      // 如果响应状态码为401说明token失效或过期，则需要刷新token
      return refreshToken().then(() => {
        // 如果刷新成功，则把之前失败的请求再继续发出去
        // cfg 是一个对象，其中包含本次失败请求相关的那些配置信息，例如 url、method 都有
        console.log('刷新成功，再去请求上一次失败的接口')
        return request(cfg)
      })
    }

    // 从错误消息映射表中查找对应状态码的错误消息
    let errMsg = cfg.errMsgMap ? cfg.errMsgMap[res.status] : ''
    if (!errMsg) {
      // 如果没有在映射表中找到，那么就用原始响应的错误消息
      const msg = res.data.message
      errMsg = msg instanceof String ? msg : JSON.stringify(msg)
    }
    Toast.fail(errMsg)
    // 把错误对象传递下去
    throw err // throw err和return Promise.reject(err)是一样的效果，请回忆Promise链式调用then函数相关知识点
  }
)

export default request
